package spring.cloud.tasks.executor.executor;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import spring.cloud.tasks.common.nodepaths.EnabledTaskNodePaths;
import spring.cloud.tasks.common.nodepaths.TaskNodePaths;
import spring.cloud.tasks.executor.executor.task.TaskExecutor;
import spring.cloud.tasks.executor.executor.task.task_configuration.TaskConfiguration;


@Slf4j
@Setter
@Getter
class TaskExecutorInitListener implements TreeCacheListener {

    private final TaskExecutorInitAndTaskItemAssignListenerService taskExecutorInitAndTaskItemAssignListenerService;

    public TaskExecutorInitListener(TaskExecutorInitAndTaskItemAssignListenerService taskExecutorInitAndTaskItemAssignListenerService) {
        this.taskExecutorInitAndTaskItemAssignListenerService = taskExecutorInitAndTaskItemAssignListenerService;
    }

    @Override
    public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
        if (treeCacheEvent == null) {
            return;
        }
        ChildData childData = treeCacheEvent.getData();
        if (childData == null) {
            return;
        }
        String path = childData.getPath();
        if (path == null || path.equals(EnabledTaskNodePaths.ROOT)) {
            return;
        }
        String taskId = path.substring(EnabledTaskNodePaths.ROOT.length() + "/".length());
        TreeCacheEvent.Type type = treeCacheEvent.getType();
        if (type == null) {
            return;
        }
        if (type.equals(TreeCacheEvent.Type.NODE_ADDED) || type.equals(TreeCacheEvent.Type.NODE_UPDATED)) {
            log.info("待创建任务执行器:" + taskId);
            if (!taskExecutorInitAndTaskItemAssignListenerService.executor.taskIdToTaskExecutorMap.taskIdSet.contains(taskId)) {
                TaskExecutor taskExecutor = initTaskExecutor(taskExecutorInitAndTaskItemAssignListenerService.executor, taskId, taskExecutorInitAndTaskItemAssignListenerService);
                if (taskExecutor != null) {
                    taskExecutorInitAndTaskItemAssignListenerService.executor.taskIdToTaskExecutorMap.taskIdSet.add(taskId);
                    taskExecutorInitAndTaskItemAssignListenerService.executor.taskIdToTaskExecutorMap.addTaskExecutor(taskId, taskExecutor);
                    log.info("任务执行器创建成功:" + taskId);
                } else {
                    log.error("任务执行器创建失败:" + taskId);
                }
            } else {
                log.info("任务执行器已经存在", taskId);
            }
        } else if (type.equals(TreeCacheEvent.Type.NODE_REMOVED)) {
            log.info("待删除任务执行器:" + taskId);
            if (taskExecutorInitAndTaskItemAssignListenerService.executor.taskIdToTaskExecutorMap.taskIdSet.contains(taskId)) {
                TaskExecutor taskExecutor = taskExecutorInitAndTaskItemAssignListenerService.executor.taskIdToTaskExecutorMap.getTaskExecutor(taskId);
                if (taskExecutor != null) {
                    taskExecutor.shutdown();
                }
            }
        }

    }

    private TaskExecutor initTaskExecutor(Executor executor, String taskId, TaskExecutorInitAndTaskItemAssignListenerService taskInitService) {
        try {
            log.info("开始创建任务执行器创建");
            TaskConfiguration taskConfiguration = new TaskConfiguration(taskInitService.curator, taskId);
            if (taskConfiguration.isDeleting()) {
                String executorNodePath = TaskNodePaths.getTaskExecutorNodePath(taskId, taskInitService.executorId);
                taskInitService.curator.delete(executorNodePath);
                log.info("当前任务正在删除中,忽略本次任务执行器创建");
                return null;
            }
            TaskExecutor taskExecutor = new TaskExecutor(executor, taskInitService.curator, taskConfiguration, taskInitService);
            taskExecutor.init();
            taskInitService.executor.taskIdToTaskExecutorMap.addTaskExecutor(taskId, taskExecutor);
            return taskExecutor;
        } catch (Throwable t) {
            log.info("任务执行器创建失败:" + t.getMessage(), t);
            return null;
        }
    }
}
